﻿using Common.Communication;
using Common.Device.DeviceDb;
using Common.Device.Interfaces;
using Common.Tool.DataTools;
using Modbus;
using Modbus.Enums;
using NPOI.SS.Formula.Functions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;

namespace Fct
{
    public class FctModBus3SerialPort : ModbusRtuClient, IFct3
    {
        byte station;
        public FctModBus3SerialPort(UseDevice device) : base(device.name, device.port, Convert.ToInt32(device.parameter), 1500, EndianFormat.ABCD, Convert.ToByte(device.addr, 16), false)
        {
            station = Convert.ToByte(device.addr);
        }
        #region 继电器控制
        
        ///// <summary>
        ///// 闭合通道
        ///// </summary>
        ///// <param name="testModel"></param>
        ///// <returns></returns>
        //public bool SetChannel(List<int> closeChannels, List<int> openChannels)
        //{
        //    try
        //    {
        //        var write = new Result<byte[]>();
        //        ushort addrByte = 0;
        //        //设置指令
        //        byte[] order = SetChannel(closeChannels, openChannels, addrByte);
        //        //发送指令并返回
        //        write = WriteThenRead(order, wait: 100);
        //        //byte[] recieve = SendAndGet(testModel, order);
        //        //期望
        //        byte[] want = SetChannelOk(addrByte);
        //        //比对
        //        if (!write.IsSucceed)
        //        {
        //            result.IsSucceed = false;
        //            result.Err = "自动测试通信失败";
        //            AppendTip(Name, result.Err);
        //            return result.EndTime();
        //        }
        //        if (recieve.Length == 0 ||
        //            DeviceEntity.BLL.ConvertBLL.Equal(testModel.richTextBoxInfo, want, recieve) == false)
        //        {
        //            //比对失败
        //            testModel.result = "设置继电器失败";
        //            return false;
        //        }
        //        return true;
        //    }
        //    catch (Exception ex)
        //    {
        //        throw ex;
        //    }
        //}
        /// <summary>
        /// 断开所有通道
        /// </summary>
        /// <param name="testModel"></param>
        /// <returns></returns>
        //public bool OpenAllChannel(Model.TestModel testModel)
        //{
        //    try
        //    {
        //        if (testModel.testDevice.socket != null && testModel.testDevice.socket.Connected == false)
        //        {
        //            testModel.result = testModel.testDevice.addr + "连接失败";
        //            return false;
        //        }
        //        ushort addrByte = Convert.ToUInt16(testModel.testDevice.socket != null ? testModel.testDevice.parameter : testModel.addr, 16);
        //        //设置指令
        //        byte[] order = OpenAllChannel(addrByte);
        //        //发送指令并返回
        //        byte[] recieve = SendAndGet(testModel, order);
        //        //期望
        //        byte[] want = OpenAllChannelOk(addrByte);
        //        //比对
        //        if (recieve.Length == 0 ||
        //            DeviceEntity.BLL.ConvertBLL.Equal(testModel.richTextBoxInfo, want, recieve) == false)
        //        {
        //            //比对失败
        //            testModel.result = "断开所有继电器失败";
        //            return false;
        //        }
        //        return true;
        //    }
        //    catch (Exception ex)
        //    {
        //        throw ex;
        //    }
        //}
        /// <summary>
        /// 闭合所有通道
        /// </summary>
        /// <param name="testModel"></param>
        /// <returns></returns>
        //public bool CloseAllChannel(Model.TestModel testModel)
        //{
        //    try
        //    {
        //        var write = new Result();
        //        if (testModel.testDevice.socket != null && testModel.testDevice.socket.Connected == false)
        //        {
        //            testModel.result = testModel.testDevice.addr + "连接失败";
        //            return false;
        //        }
        //        ushort addrByte = Convert.ToUInt16(testModel.testDevice.socket != null ? testModel.testDevice.parameter : testModel.addr, 16);
        //        //设置指令
        //        byte[] order = CloseAllChannel(addrByte);
        //        //发送指令并返回
        //        byte[] recieve = SendAndGet(testModel, order);
        //        //期望
        //        byte[] want = CloseAllChannelOk(addrByte);
        //        //比对
        //        if (recieve.Length == 0 ||
        //            DeviceEntity.BLL.ConvertBLL.Equal(testModel.richTextBoxInfo, want, recieve) == false)
        //        {
        //            //比对失败
        //            testModel.result = "闭合所有继电器失败";
        //            return false;
        //        }
        //        return true;
        //    }
        //    catch (Exception ex)
        //    {
        //        throw ex;
        //    }
        //}
        #endregion
        #region 继电器控制
        /// <summary>
        /// 设置继电器
        /// </summary>
        /// <param name="close">闭合通道</param>
        /// <param name="open">断开通道</param>
        /// <param name="addr">485地址</param>
        /// <returns></returns>
        public static byte[] SetChannel(List<int> close, List<int> open, ushort addr)
        {
            int lenH = (13 + close.Count + open.Count) >> 8;
            int lenL = (13 + close.Count + open.Count) & 0xFF;
            int addrH = addr >> 8;
            int addrL = addr & 0xFF;
            List<int> bytes = new List<int> { 0x55, 0xAA, lenH, lenL, addrH, addrL, 0x02, 0x01, 0x01, };
            bytes.Add(close.Count());
            bytes.AddRange(close);
            bytes.Add(open.Count());
            bytes.AddRange(open);
            var order = bytes.ConvertAll<byte>(it => Convert.ToByte(it)).ToArray();
            return ByteHelper.Crc16(order, order.Length,true);
        }
        /// <summary>
        /// 设置继电器成功
        /// </summary>
        /// <param name="channel">通道号</param>
        /// <param name="addr">485地址</param>
        /// <returns></returns>
        public static byte[] SetChannelOk(ushort addr)
        {
            int addrH = addr >> 8;
            int addrL = addr & 0xFF;
            byte[] bytes = new byte[] { 0x55, 0xAA, 0x00, 0x0B, Convert.ToByte(addrH), Convert.ToByte(addrL), 0x02, 0x01, 0x01 };
            return ByteHelper.Crc16(bytes, bytes.Length, true);
        }
        /// <summary>
        /// 断开所有通道
        /// </summary>
        /// <param name="addr">485地址</param>
        /// <returns></returns>
        public static byte[] OpenAllChannel(ushort addr)
        {
            int addrH = addr >> 8;
            int addrL = addr & 0xFF;
            byte[] bytes = new byte[] { 0x55, 0xAA, 0x00, 0x0B, Convert.ToByte(addrH), Convert.ToByte(addrL), 0x02, 0x01, 0x03 };
            return ByteHelper.Crc16(bytes, bytes.Length, true);
        }
        /// <summary>
        /// 断开所有通道成功
        /// </summary>
        /// <param name="addr">485地址</param>
        /// <returns></returns>
        public static byte[] OpenAllChannelOk(ushort addr)
        {
            int addrH = addr >> 8;
            int addrL = addr & 0xFF;
            byte[] bytes = new byte[] { 0x55, 0xAA, 0x00, 0x0B, Convert.ToByte(addrH), Convert.ToByte(addrL), 0x02, 0x01, 0x03 };
            return ByteHelper.Crc16(bytes, bytes.Length, true);
        }
        /// <summary>
        /// 闭合所有通道
        /// </summary>
        /// <param name="addr">485地址</param>
        /// <returns></returns>
        public static byte[] CloseAllChannel(ushort addr)
        {
            int addrH = addr >> 8;
            int addrL = addr & 0xFF;
            byte[] bytes = new byte[] { 0x55, 0xAA, 0x00, 0x0B, Convert.ToByte(addrH), Convert.ToByte(addrL), 0x02, 0x01, 0x02 };
            return ByteHelper.Crc16(bytes, bytes.Length, true); ;
        }
        /// <summary>
        /// 闭合所有通道成功
        /// </summary>
        /// <param name="addr">485地址</param>
        /// <returns></returns>
        public static byte[] CloseAllChannelOk(ushort addr)
        {
            int addrH = addr >> 8;
            int addrL = addr & 0xFF;
            byte[] bytes = new byte[] { 0x55, 0xAA, 0x00, 0x0B, Convert.ToByte(addrH), Convert.ToByte(addrL), 0x02, 0x01, 0x02 };
            return ByteHelper.Crc16(bytes, bytes.Length, true); ;
        }

        public Result<bool> GetJdq(int index)
        {
            throw new NotImplementedException();
        }

        public Result<bool> SetJdq(List<int> closeChannels, List<int> openChannels)
        {
            try
            {
                var result = new Result<bool>();
                var write = new Result<byte[]>();
                ushort addrByte = 0;
                //设置指令
                byte[] order = SetChannel(closeChannels, openChannels, addrByte);
                //发送指令并返回
                write = WriteThenRead(order, wait: 100);
                //byte[] recieve = SendAndGet(testModel, order);
                //期望
                byte[] want = SetChannelOk(addrByte);
                //比对
                if (!write.IsSucceed)
                {
                    result.IsSucceed = false;
                    result.Err = "设置继电器失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                if (write.Value.Length == 0 ||  Equal(want, write.Value) == false)
                {
                    //比对失败

                    result.IsSucceed = false;
                    result.Err = "设置继电器失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                return result.EndTime();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            
        }

        public Result<bool> GetDp(int index)
        {
            throw new NotImplementedException();
        }
        #endregion 继电器控制/// <summary>
        /// 字节比对
        /// </summary>
        /// <param name="richTextBox">日志</param>
        /// <param name="want">期望</param>
        /// <param name="recieve">实际</param>
        /// <returns></returns>
        public  bool Equal( byte[] want, byte[] recieve)
        {
            try
            {
                //返回值为空
                if (recieve.Length == 0)
                {
                    return false;
                }
                //字节比对错误
                if (ByteHelper.EqualBytes(recieve, want) == false)
                {
                    //比对信息
                    string err = "期望:" + ByteHelper.BytesToString(want) + "\r\n" +
                        "响应:" + ByteHelper.BytesToString(recieve);
                    AppendInfo(Name, $"读取继电器{err}状态");
                    return false;
                }
                return true;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }
}
